from django import template
from django.contrib.auth.models import User
from django.contrib.humanize.templatetags.humanize import intcomma
from django.db.models import Max
from bibliophile.models import Book, Progress

register = template.Library()

@register.simple_tag
def pages_read(user=None):
    if not user:
        user = User.objects.get(pk=1)
    
    total_pages = 0
    for book in user.book_set.filter(progress_mode='p'):
        max_mile = book.progress_set.aggregate(Max('milestone'))
        total_pages += max_mile.get('milestone__max', 0) or 0
    return intcomma(total_pages)

class BooksNode(template.Node):
    """
    Injects a list of finished/unfinished/planned books into the context for
    the user to render.

    TODO: Make this work on a site with multiple users.
    """
    def __init__(self, count, varname, finished=False, planned=False):
        self.count = int(count)
        self.varname = varname
        self.finished = finished
        self.planned = planned

    def render(self, context):
        """
        Determines which books should be returned.
        """

        if self.planned:
            # books planned to read
            qs = Book.objects.order_by('?')
            books = [b for b in qs if b.progress_set.count() == 0]
            context[self.varname] = books[:self.count]
            return ''

        if self.finished:
            # finished books
            op = '>='
        else:
            # books that have been started but not finished
            op = '<'

        params = ("bibliophile_book.id = book_id",
                  "milestone %s bibliophile_book.maximum_progress" % op)

        qs = Progress.objects.extra(where=params,
                                    tables=['bibliophile_book'],
                                    order_by=['-date_achieved', '-milestone'])
        books = []
        for progress in qs:
            if progress.book not in books:
                if (not self.finished and progress.book.progress < 100) or \
                    self.finished:
                    books.append(progress.book)

                if len(books) >= self.count: break

        context[self.varname] = books
        return ''

def finished_books(parser, token):
    try:
        tag, count, a, varname = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('finished_books syntax: {% finished_books 5 as finished %}')

    return BooksNode(count, varname, finished=True)

def unfinished_books(parser, token):
    try:
        tag, count, a, varname = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('unfinished_books syntax: {% unfinished_books 5 as unfinished %}')

    return BooksNode(count, varname, finished=False)

def planning_to_read(parser, token):
    try:
        tag, count, a, varname = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('planning_to_read syntax: {% planning_to_read 5 as planned %}')

    return BooksNode(count, varname, planned=True)

register.tag(finished_books)
register.tag(unfinished_books)
register.tag(planning_to_read)
